home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 19 / madtrb14.zip / MAILSYS.INC < prev    next >
Text File  |  1985-10-05  |  17KB  |  656 lines

  1. const
  2.   numsects = 12;
  3.   maxlength = 24;
  4.   maxlenstr = '24';
  5.  
  6. type
  7.   messages = record
  8.               number:  integer;
  9.               sender:  integer;
  10.               recver:  integer;
  11.               subject: name;
  12.               date:    name;
  13.               private: boolean;
  14.               section: byte;
  15.               repto:   integer;
  16.               reply:   integer;
  17.               recved:  boolean;
  18.             end;
  19.   sectname = array[1..numsects] of string[20];
  20.   messtext = array[1..maxlength] of line;
  21.  
  22. const
  23.   sect : sectname = ('1: General',
  24.                      '2: Ohio Scientific',
  25.                      '3: CP/M',
  26.                      '4: Buy and Sell',
  27.                      '5: 6502',
  28.                      '6: Turbo Pascal',
  29.                      '7: C',
  30.                      '8: CompuServe',
  31.                      '9: 6809',
  32.                      '10: Kaypro',
  33.                      '11: MS-DOS',
  34.                      '12: TurboBBS code');
  35.  
  36.   maxmess = 52;   { <-- Maximum number of messages - this limit due to CP/M
  37.                     maximum directory size on Kaypro.}
  38.  
  39. var
  40.   messagefile: file of messages;
  41.   count: integer;
  42.   messtable: array[1..maxmess] of messages;
  43.   preformat: boolean;
  44.  
  45. function namemess(number: integer): name;
  46.  
  47.   var
  48.     filename: name;
  49.  
  50.   begin
  51.     str((10000 + number):6, filename);
  52.     namemess := messdrive + 'MESS' + copy(filename, 3, 4) + '.TXT';
  53.   end;
  54.  
  55. procedure kill(x: integer);
  56.  
  57.   var
  58.     victim: text;
  59.  
  60.   begin
  61.     assign(victim, namemess(x));
  62.     erase(victim);
  63.   end;
  64.  
  65. function secure(tabloc: byte): boolean;
  66.  
  67.   begin
  68.     with messtable[tabloc] do
  69.       secure := ((usernum <> sender)
  70.                 and (usernum <> recver)
  71.                 and (access < sysop))
  72.                 or (usernum = 0);
  73.   end;
  74.  
  75. procedure listsections;
  76.  
  77.   var
  78.     loopvar : integer;
  79.     temp    : line;
  80.  
  81.   begin
  82.     if cts then begin
  83.       clearsc;
  84.       lineout('Sections:' + cr + lf);
  85.       for loopvar := 1 to numsects do begin
  86.         lineout(sect[loopvar]);
  87.       end;
  88.     end;
  89.   end;
  90.  
  91. procedure status;
  92.  
  93.   var
  94.     temp: line;
  95.  
  96.   begin
  97.     if cts then begin
  98.       lineout(cr + lf + 'Caller: ' + caller);
  99.       str(access:1, temp);
  100.       lineout('Access level: ' + temp);
  101.       str(count:2, temp);
  102.       lineout('System has ' + temp + ' messages;');
  103.       str(nextmess:4, temp);
  104.       lineout('Next message is: ' + temp);
  105.     end;
  106.   end;
  107.  
  108. procedure initmess;
  109.  
  110.   begin
  111.     if cts then lineout(cr + lf + 'Initializing message system...');
  112.     count := 0;
  113.     nextmess := 1;
  114.     assign(messagefile, 'MESSAGES.BBS');
  115.     {$I-} reset(messagefile) {$I+};
  116.     if IOresult = 0 then begin
  117.       while (count < maxmess) and not eof(messagefile) do begin
  118.         count := count + 1;
  119.         read(messagefile, messtable[count]);
  120.       end;
  121.       close(messagefile);
  122.       if count > 0 then nextmess := messtable[count].number + 1;
  123.     end;
  124.     unload;
  125.     messopen := true;
  126.     status;
  127.   end;
  128.  
  129. function findmessage(x: integer): byte;
  130.  
  131.   var
  132.     loop: byte;
  133.  
  134.   begin
  135.     loop := 0;
  136.     findmessage := 0;
  137.     if count > 0 then begin
  138.       repeat
  139.         loop := loop + 1;
  140.       until (loop >= count) or (messtable[loop].number >= x);
  141.       if messtable[loop].number = x
  142.         then findmessage := loop
  143.         else findmessage := 0;
  144.     end;
  145.   end;
  146.  
  147. function getname(usernum: integer): person;
  148.  
  149.   var
  150.     tempid: sysid;
  151.  
  152.   begin
  153.     seek(idfile, usernum-1);
  154.     read(idfile, tempid);
  155.     getname := tempid.user;
  156.   end;
  157.  
  158. procedure header(tabloc: byte);
  159.  
  160.   var
  161.     temp: line;
  162.  
  163.   begin
  164.     if cts then with messtable[tabloc] do begin
  165.       str(number:4, temp);
  166.       stringout(cr + lf);
  167.       if private then stringout('Private ');
  168.       stringout('Message #' + temp);
  169.       temp := getname(sender);
  170.       stringout(' is from: ' + temp);
  171.       if recver > 0 then temp := getname(recver) else temp := 'ALL';
  172.       if recved then temp := temp + ' (Rec''d)';
  173.       lineout(' to: ' + temp);
  174.       stringout('Subj: ' + subject);
  175.       if clockin then stringout('  Time: ' + date);
  176.       if sectsin then stringout('  Section ' + sect[section]);
  177.       lineout(space);
  178.     end;
  179.   end;
  180.  
  181. procedure destroy(tabloc: byte);
  182.  
  183.   var
  184.     loop: byte;
  185.  
  186.   begin
  187.     if tabloc > 0 then begin
  188.       kill(messtable[tabloc].number);
  189.       for loop := tabloc+1 to count do
  190.         messtable[loop-1] := messtable[loop];
  191.       count := count - 1;
  192.       lineout('Message deleted.');
  193.     end;
  194.   end;
  195.  
  196. procedure readfile(tabloc: byte);
  197.  
  198.   begin
  199.     if cts then begin
  200.       outfile(namemess(messtable[tabloc].number));
  201.       lineout(space);
  202.       if (messtable[tabloc].recver = usernum) and (usernum > 0)
  203.         then messtable[tabloc].recved := true;
  204.       if cts and (tabloc > 1) and not secure(tabloc) then begin
  205.         if getcap('Delete (Y/N)? ') = 'Y' then destroy(tabloc);
  206.       end;
  207.     end;
  208.   end;
  209.  
  210. procedure readmess(number: integer);
  211.  
  212.   var tabloc: byte;
  213.  
  214.   begin
  215.     tabloc := findmessage(number);
  216.     if tabloc = 0 then lineout('Message not found.')
  217.       else if (secure(tabloc) and messtable[tabloc].private)
  218.         then lineout('Private message.')
  219.         else begin
  220.           header(tabloc);
  221.           readfile(tabloc);
  222.         end;
  223.   end;
  224.  
  225. procedure delmessage(x: integer);
  226.  
  227.   var
  228.     tabloc: byte;
  229.  
  230.   begin;
  231.     tabloc := findmessage(x);
  232.     if cts then begin
  233.       if tabloc > 0 then begin
  234.         if not secure(tabloc) then begin
  235.           header(tabloc);
  236.           if getcap('Are you sure (Y/N)? ') = 'Y' then destroy(tabloc);
  237.         end
  238.         else lineout('You can''t delete that message.');
  239.       end
  240.       else lineout('Message not found.');
  241.     end;
  242.   end;
  243.  
  244. function getid(prompt: line): integer;
  245.  
  246.   var
  247.     temp: person;
  248.  
  249.   begin
  250.     temp := allcaps(getinput(prompt, 28, echo));
  251.     if temp = '' then getid := 0 else getid := findid(temp);
  252.   end;
  253.  
  254. procedure deletex;
  255.  
  256.   begin
  257.     if cts then delmessage(getint(nextmess - 1, 0, 'Delete: which number? '));
  258.   end;
  259.  
  260. procedure quickscan;
  261.  
  262.   var
  263.     loop: byte;
  264.     first: integer;
  265.  
  266.   begin
  267.     if cts then begin
  268.       first := getint(nextmess - 1, lastmess + 1, 'Start scan at which number (* for new)? ');
  269.       if first > 0 then begin
  270.         clearsc;
  271.         for loop := 1 to count do
  272.           if (messtable[loop].number >= first)
  273.             and not (secure(loop) and messtable[loop].private)
  274.             and cts and not cancelled
  275.             then header(loop);
  276.       end;
  277.     end;
  278.   end;
  279.  
  280. procedure readind;
  281.  
  282.   var
  283.    messnum: integer;
  284.    tabloc : byte;
  285.  
  286.   begin
  287.     repeat
  288.       messnum := getint(nextmess - 1, 0, 'Read which number (enter 0 to quit)? ');
  289.       if messnum > 0 then readmess(messnum);
  290.     until (messnum <= 0) or not cts;
  291.   end;
  292.  
  293. procedure messagesearch(first:byte; fromnum, tonum:integer; sectnum:byte);
  294.  
  295.   var
  296.     loop: byte;
  297.     inch: char;
  298.     oldnum: integer;
  299.     matched: boolean;
  300.  
  301.   begin
  302.     matched := false;
  303.     inch := null;
  304.     loop := first;
  305.     while cts and (loop <= count) and (inch <> 'Q') and (count <> 0) do begin
  306.       oldnum := messtable[loop].number;
  307.       if ((fromnum = 0) or (fromnum = messtable[loop].sender))
  308.         and ((tonum = 0) or (tonum = messtable[loop].recver))
  309.         and ((sectnum = 0) or (sectnum = messtable[loop].section))
  310.         and not (secure(loop) and messtable[loop].private)
  311.       then begin
  312.         matched := true;
  313.         cancelled := false;
  314.         header(loop);
  315.         inch := getcap('Read (Y/N/Quit)? ');
  316.         if inch = 'Y' then readfile(loop);
  317.       end;
  318.       if messtable[loop].number = oldnum then loop := loop + 1;
  319.     end;
  320.     if cts and not matched then lineout('No messages found.');
  321.   end;
  322.  
  323. function findfirst(startmess: integer): byte;
  324.  
  325.   var loop : byte;
  326.  
  327.   begin
  328.     loop := 0;
  329.     if count > 0 then repeat
  330.       loop := loop + 1;
  331.     until (messtable[loop].number >= startmess) or (loop = count);
  332.     findfirst := loop;
  333.   end;
  334.  
  335. function getfirst: byte;
  336.  
  337.   var
  338.     startmess : integer;
  339.  
  340.   begin
  341.     repeat
  342.       startmess := getint(nextmess - 1, lastmess + 1, 'Start at which message (? for stats, * for new)? ');
  343.       if startmess = -1 then status;
  344.     until (startmess <> -1) or not cts;
  345.     if startmess = 0 then getfirst := 0
  346.       else getfirst := findfirst(startmess);
  347.   end;
  348.  
  349. procedure readfrom;
  350.  
  351.   var
  352.     fromnum: integer;
  353.     first: byte;
  354.  
  355.   begin
  356.     if cts then begin
  357.       fromnum := getid('Enter name of sender: ');
  358.       if fromnum < 1
  359.         then stringout('Not a registered user name.')
  360.         else begin
  361.           first := getfirst;
  362.           if first > 0 then messagesearch(first, fromnum, 0, 0);
  363.         end;
  364.     end;
  365.   end;
  366.  
  367. procedure readto;
  368.  
  369.   var
  370.     tonum: integer;
  371.     first: byte;
  372.  
  373.   begin
  374.     if cts then begin
  375.       tonum := getid('Enter name of addressee: ');
  376.       if tonum < 1
  377.         then stringout('Not a registered user name.')
  378.         else begin
  379.           first := getfirst;
  380.           if first > 0 then messagesearch(first, 0, tonum, 0);
  381.         end;
  382.     end;
  383.   end;
  384.  
  385. procedure readsect;
  386.  
  387.   var
  388.     first: byte;
  389.     inch: integer;
  390.  
  391.   begin
  392.     if cts then repeat
  393.       if sectsin then
  394.         inch := getint(numsects, 0, 'Enter section number (0 for all, ? for list): ')
  395.         else inch := 1;
  396.       case inch of
  397.         -1          : listsections;
  398.          0..numsects: begin
  399.                          first := getfirst;
  400.                          if first > 0 then messagesearch(first, 0, 0, inch);
  401.                        end;
  402.       end;
  403.     until (inch <> -1) or not cts;
  404.   end;
  405.  
  406. procedure receive;
  407.  
  408.   var
  409.     uchar: char;
  410.  
  411.   begin
  412.     if cts then begin
  413.       clearsc;
  414.       if not expert then outfile(readmenu);
  415.       repeat
  416.         uchar := getcap('Read mode: (A,I,F,T,S, or ? for menu)? ');
  417.         if uchar = '?' then outfile(readmenu);
  418.       until (uchar in ['A','I','F','T','S',cr]) or not cts;
  419.       if uchar = 'I' then readind;
  420.       if cts and (uchar <> 'I') then begin
  421.         case uchar of
  422.           'A': messagesearch(getfirst,0,0,0);
  423.           'F': readfrom;
  424.           'T': readto;
  425.           'S': readsect;
  426.         end;
  427.       end;
  428.     end;
  429.   end;
  430.  
  431. procedure closemess;
  432.  
  433.   var
  434.     loop: byte;
  435.  
  436.   begin
  437.     rewrite(messagefile);
  438.     for loop := 1 to count do
  439.       write(messagefile, messtable[loop]);
  440.     close(messagefile);
  441.     messopen := false;
  442.   end;
  443.  
  444. {make "enter" an overlay procedure and make filesys another one to save space}
  445. procedure enter;
  446.  
  447.   var
  448.     tabloc: byte;
  449.     messbuff: messtext;
  450.     linenum: byte;
  451.     inch: char;
  452.  
  453.   procedure compose(var block: messtext; var linenum: byte);
  454.  
  455.     var
  456.       temp: name;
  457.  
  458.     begin
  459.       lineout(cr + lf + 'Enter message text: ' + maxlenstr + ' lines of 80 chars max.');
  460.       lineout('An empty line ends entry. "." at start of line forces new line.');
  461.       lineout(space);
  462.       if linenum < maxlength then repeat
  463.         linenum := linenum + 1;
  464.         str(linenum:2, temp);
  465.         stringout(temp + ': ');
  466.         block[linenum] := inputstring(echo);
  467.       until (linenum = maxlength) or (block[linenum] = '') or not cts;
  468.       if block[linenum] = '' then linenum := linenum - 1;
  469.     end;
  470.  
  471.   procedure list(var block: messtext; first, last: byte);
  472.  
  473.     var
  474.       loop: byte;
  475.       temp: name;
  476.  
  477.     begin
  478.       if (first > 0) and (last > 0) and cts then begin
  479.         loop := first;
  480.         while (loop <= last) and (not cancelled) and cts do begin
  481.           str(loop:2, temp);
  482.           stringout(temp + ': ');
  483.           lineout(block[loop]);
  484.           loop := loop + 1;
  485.         end;
  486.         lineout(space);
  487.       end;
  488.     end;
  489.  
  490.   procedure delline(var block: messtext; linenum: byte; var maxline: byte);
  491.  
  492.     var temp: char;
  493.         loop: byte;
  494.  
  495.     begin
  496.       list(block, linenum, linenum);
  497.       if cts and (linenum > 0) then begin
  498.         temp := getcap('Delete: are you sure (Y/N)? ');
  499.         if temp = 'Y' then begin
  500.           for loop := linenum+1 to maxline do block[loop-1] := block[loop];
  501.           block[maxline] := '';
  502.           maxline := pred(maxline);
  503.           lineout('Line deleted.');
  504.         end;
  505.       end;
  506.     end;
  507.  
  508.   procedure edit(var block: messtext; linenum: byte);
  509.  
  510.     var
  511.       oldstring: line;
  512.       newstring: line;
  513.       posn     : integer;
  514.  
  515.     begin
  516.       if (linenum > 0) and cts then begin
  517.         list(block, linenum, linenum);
  518.         oldstring := getinput('Enter string to replace: ', 80, echo);
  519.         newstring := getinput('Enter replacement: ', 80, echo);
  520.         posn := pos(oldstring, block[linenum]);
  521.         if posn <> 0 then begin
  522.           delete(block[linenum], posn, length(oldstring));
  523.           insert(newstring, block[linenum], posn);
  524.           list(block, linenum, linenum);
  525.         end
  526.         else lineout('Old string not found.');
  527.         lineout(space);
  528.       end;
  529.     end;
  530.  
  531.   procedure replace(var block: messtext; linenum: byte);
  532.  
  533.     begin
  534.       if (linenum > 0) and cts then begin
  535.         lineout('Old line:');
  536.         list(block, linenum, linenum);
  537.         lineout('Enter new line:');
  538.         stringout('? ');
  539.         block[linenum] := inputstring(echo);
  540.       end;
  541.     end;
  542.  
  543.   function whichline(linenum: byte): byte;
  544.  
  545.     var
  546.       temp: name;
  547.       x   : integer;
  548.  
  549.     begin
  550.       str(linenum:2, temp);
  551.       x := getint(linenum, 0, ' Which line? (1 - ' + temp + ')? ');
  552.       if (x <= 0) or not cts then whichline := 0 else whichline := x;
  553.     end;
  554.  
  555.   procedure newheader(var entry: messages);
  556.  
  557.     var
  558.       temp, tonum: integer;
  559.  
  560.     begin
  561.       if cts then begin
  562.         entry.sender := usernum;
  563.         tonum := getid('Who to (RETURN or ENTER key for ALL)? ');
  564.         if tonum = 0 then lineout('Message to: ALL');
  565.         entry.recver := tonum;
  566.         entry.subject := getinput('Subject (14 characters max.)? ', 14, echo);
  567.         if clockin then begin
  568.           clock(month, date, hour, min, sec);
  569.           entry.date := time(month, date, hour, min, sec);
  570.         end;
  571.         if sectsin then repeat
  572.           temp := getint(numsects, 0, 'Which section (or "?" for list)? ');
  573.           if temp = -1 then listsections;
  574.           if temp in [1..numsects] then entry.section := temp;
  575.         until (temp in  [1..numsects]) or not cts
  576.         else entry.section := 1;
  577.         if tonum > 0 then entry.private := getcap('Private message (Y/N)? ')='Y'
  578.         else entry.private := false;
  579.         entry.reply := 0;
  580.         entry.repto := 0;
  581.         entry.number := nextmess;
  582.         entry.recved := false;
  583.       end;
  584.     end;
  585.  
  586.   procedure storemess(var block: messtext; tabloc, lastline: byte);
  587.  
  588.     var
  589.       outfile: text;
  590.       linenum: byte;
  591.  
  592.     begin
  593.       if cts then begin
  594.         lineout('Writing message to disk...');
  595.         assign(outfile, namemess(nextmess));
  596.         rewrite(outfile);
  597.         linenum := 1;
  598.         while linenum <= lastline do begin
  599.           if (copy(block[linenum],1,1) = '.') or preformat then begin
  600.             writeln(outfile);
  601.             if not preformat then
  602.               block[linenum] := copy(block[linenum], 2, length(block[linenum])-1);
  603.           end
  604.           else write(outfile, ' ');
  605.           write(outfile, block[linenum]);
  606.           linenum := linenum + 1;
  607.         end;
  608.         writeln(outfile);
  609.         close(outfile);
  610.         unload;
  611.         nextmess := nextmess + 1;
  612.         count := count + 1;
  613.       end;
  614.     end;
  615.  
  616.   begin
  617.     preformat := false;
  618.     if cts then begin
  619.       clearsc;
  620.       if access < reg then lineout('You cannot enter messages yet: Use [A]pply command.')
  621.       else begin
  622.         tabloc := count + 1;
  623.         if tabloc > maxmess then lineout('No message space left.')
  624.         else begin
  625.           repeat
  626.             newheader(messtable[tabloc]);
  627.             header(tabloc);
  628.             inch := getcap('Is this OK (Y/N/Abort)? ');
  629.           until (inch <> 'N') or not cts;
  630.           unload;
  631.           if inch <> 'A' then begin
  632.             linenum := 0;
  633.             compose(messbuff, linenum);
  634.             if not expert then outfile(editmenu);
  635.             repeat
  636.               inch := getcap('Edit command: A,C,D,E,L,P,R,S or ? for menu? ');
  637.               case inch of
  638.                 'C': compose(messbuff, linenum);
  639.                 'D': delline(messbuff, whichline(linenum), linenum);
  640.                 'E': edit(messbuff, whichline(linenum));
  641.                 'L': list(messbuff, whichline(linenum), linenum);
  642.                 'P': begin preformat := true; storemess(messbuff, tabloc, linenum); end;
  643.                 'R': replace(messbuff, whichline(linenum));
  644.                 'S': storemess(messbuff, tabloc, linenum);
  645.                 '?': outfile(editmenu);
  646.               end;
  647.             until (inch = 'A')
  648.                or (inch = 'S')
  649.                or (inch = 'P')
  650.                or not cts;
  651.           end;
  652.         end;  {2nd else}
  653.       end;  {1st else}
  654.     end; {if cts}
  655.   end; {enter}
  656.